﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once

#include "GnufBase.h"
/// \file GnufDynamicZoneMenuManager.h
namespace gnuf {
    /// \brief 动态面板弹出菜单管理器
    class GNUF_BASE_EXPORT DynamicZoneMenuManager
    {
    public:
        ~DynamicZoneMenuManager() {} ;

        /// \brief 定义菜单项的响应函数类型
        typedef typename std::function<void(const std::wstring& )> MenuItemFunction;
        typedef typename std::vector<std::pair<std::wstring, MenuItemFunction>> MenuItems;
        typedef typename std::vector<std::wstring> DynamicPanels;
        typedef typename std::vector<std::pair<std::wstring, DynamicPanels>> ForbidenPanelsForItem;
        static DynamicZoneMenuManager* get();

        /// \brief 注册一个菜单项
        /// \param caption 菜单项的标题
        /// \param function 点击菜单项后的响应函数
        bool registerMenuItem(const std::wstring& caption, const MenuItemFunction& function);

        /// \brief 反注册一个菜单项
        /// \param caption 菜单项的标题
        bool unRegisterMenuItem(const std::wstring& caption);

        /// \brief 在DynamicPanelBase上禁用指定弹出菜单项
        /// \param caption 想要禁用的菜单项标题
        /// \param key 指定的Panel
        /// \retval true 成功禁用指定菜单项
        /// \retval false 可能不存在菜单项，或是已经被禁用
        /// \see DynamicPanelBase
        bool disableMenuItemOnPanel(const std::wstring& caption, const std::wstring& key);

        /// \brief 在多个DynamicPanelBase上禁用弹出菜单项
        /// \param caption 想要禁用的菜单项标题
        /// \param panels 指定的Panel的vector
        /// \retval true 成功禁用指定菜单项
        /// \retval false 可能不存在菜单项
        /// \see DynamicPanels
        /// \note 如果指定的菜单项已经有DynamicPanels，则把传入的panels与已有的求并集
        bool disableMenuItemOnPanels(const std::wstring& caption, const DynamicPanels& panels);

        /// \brief 在DynamicPanelBase上解禁用指定弹出菜单项
        /// \param caption 想要解禁用的菜单项标题
        /// \param key 指定的Panel
        /// \retval true 成功解禁用指定菜单项
        /// \retval false 可能不存在菜单项，或是没被禁用
        bool enableMenuItemOnPanel(const std::wstring& caption, const std::wstring& key);

        /// \brief 检查弹出菜单项在DynamicPanelBase上是否处禁用状态
        /// \param caption 菜单项标题
        /// \param key 指定的Panel
        /// \retval true 没有被禁用状态
        /// \retval false 处于禁用状态
        bool checkMenuItemEnabledOnPanel(const std::wstring& caption, const std::wstring& key);

        /// \brief 查找一个菜单项对应的响应函数
        /// \param caption 菜单项的标题
        /// \return 返回一个响应函数
        MenuItems::iterator findMenuItem(const std::wstring& caption);

        /// \brief 获得所有的菜单项
        const MenuItems& getMenuItems();
    private:
        ForbidenPanelsForItem::iterator getDisabledPanelsOfMenuItem(const std::wstring& caption);
        MenuItemFunction functionOfMenuItem(const std::wstring&);
        bool haveMenuItem(const std::wstring& caption);
        DynamicZoneMenuManager() {};
        DynamicZoneMenuManager(const DynamicZoneMenuManager&) = delete;
        DynamicZoneMenuManager operator=(const DynamicZoneMenuManager&) = delete;
        
        MenuItems m_captionToFunction;

        /// \brief “菜单项标题”到“想disable这个菜单项的Panel”的映射
        ForbidenPanelsForItem m_captionToForbidenPanel;
    };

    class GNUF_BASE_EXPORT DynamicZoneMenuItemCreator
    {
    public:
        /// \brief 构造函数，用来注册一个菜单项
        /// \param caption 菜单项的标题
        /// \param function 菜单项的响应函数
        /// \param panelsWantDisableThisItem 想要disable这个菜单项的Panel
        /// \see DynamicZoneMenuManager::MenuItemFunction DynamicZoneMenuManager::DynamicPanels
        DynamicZoneMenuItemCreator(
            const std::wstring& caption, 
            const DynamicZoneMenuManager::MenuItemFunction& function, 
            const DynamicZoneMenuManager::DynamicPanels& panelsWantDisableThisItem = {});
    };
}
